using System.Collections;
using System.Collections.Generic;
using System.IO;
using Sirenix.OdinInspector;
using UnityEngine;
using UnityEngine.Serialization;
using Pangoo.Common;
using System.Linq;


#if UNITY_EDITOR
using UnityEditor;
#endif

namespace MetaTable
{

    [CreateAssetMenu(fileName = "MetaTableConfig", menuName = "MetaTable/Config", order = 0)]
    public partial class MetaTableConfig : ScriptableObject
    {

        [LabelText("命名空间")]
        public string Namespace;

        [LabelText("名字")]
        public string Name;

        [LabelText("包路径")]
        [InlineButton("GuessPackageDir", "猜测包路径")]
        public string PackageDir;


        [LabelText("运行时目录")]
        [HideInInspector]
        public string ScriptDir = "Runtime";

        [LabelText("接口目录")]
        [HideInInspector]
        public string InterfaceDir = "Interface";

        [LabelText("编辑器目录")]
        [HideInInspector]
        public string EditorDir = "Editor";


        [LabelText("资源包目录")]
        [HideInInspector]
        public string StreamResDir = "StreamRes";


#if UNITY_EDITOR
        public string AssetPath
        {
            get
            {
                return AssetDatabase.GetAssetPath(this);
            }
        }

        public bool CheckPackageDir()
        {
            if (AssetPath.StartsWith(StreamResConfigDir))
            {
                return true;
            }

            return false;
        }

        public void GuessPackageDir()
        {
            var path = AssetDatabase.GetAssetPath(this);
            if (path.IsNullOrWhiteSpace())
            {
                return;
            }
            Debug.Log($"Guess Path:{path}");
            PackageDir = Path.GetDirectoryName(path).ToPath();
            var parentDir = PathUtility.MatchParentDirs(PackageDir, new string[] { "Configs", "StreamRes" });
            if (parentDir != null)
            {
                PackageDir = parentDir;
            }

            PackageDir = PackageDir.ToPath();
        }
#endif

        public void GuessScriptDir()
        {
            if (!PackageDir.IsNullOrWhiteSpace())
            {

            }
        }

        [OnValueChanged("OnTemplateChanged")]
        [ValueDropdown("OnTemplateDropdown")]
        public MetaTableTemplate Template;

#if UNITY_EDITOR
        IEnumerable OnTemplateDropdown()
        {
            ValueDropdownList<MetaTableTemplate> ret = new();
            var assets = AssetDatabaseUtility.FindAsset<MetaTableTemplate>();
            Debug.Log($"assets:{assets.Count()}");
            ret.Add("Null", null);
            foreach (var asset in assets)
            {
                ret.Add(AssetDatabase.GetAssetPath(asset), asset);
            }
            return ret;
        }

        public void OnTemplateChanged()
        {
            if (Template == null || Template.Overviews == null || Template.Overviews.Count == 0) return;
            foreach (var overview in Template.Overviews)
            {
                bool found = false;
                foreach (var entry in Entries)
                {
                    if (entry.MetaTableType != MetaTableEntry.MetaTableTypeEnum.ReferenceRow) continue;
                    if (entry.RefConfig.Namespace.Equals(overview.Namespace)
                    && entry.RefTableName.Equals(overview))
                    {
                        found = true;
                    }
                }

                if (!found)
                {
                    var entry = new MetaTableEntry();
                    entry.MetaTableType = MetaTableEntry.MetaTableTypeEnum.ReferenceRow;
                    entry.RefTableName = overview.TableName;
                    entry.RefConfig = MetaTableUtility.GetMetaTableConfigByNamespce(overview.Namespace);
                    if (entry.RefConfig != null)
                    {
                        Entries.Add(entry);
                    }
                }
            }

        }

#endif

        [FormerlySerializedAs("Headers")]
        [LabelText("引用头文件")]
        public List<string> UsingNamespace = new List<string>()
        {
            "System",
            "System.IO",
            "System.Collections",
            "System.Collections.Generic",
            "System.Linq",
            "LitJson",
            "UnityEngine",
            "Sirenix.OdinInspector",
            "System.Xml.Serialization",
            "Pangoo.Common",
            "MetaTable"
        };

        [TableList(AlwaysExpanded = true)]
        [OnCollectionChanged("AfterChanged")]
        [TabGroup("表")]
        public List<MetaTableEntry> Entries = new List<MetaTableEntry>();


        public void AfterChanged()
        {
            foreach (var entry in Entries)
            {
                entry.Config = this;
            }
        }


        [TableList(AlwaysExpanded = true)]
        [OnCollectionChanged("AfterDataChanged")]
        [TabGroup("数据")]
        public List<MetaTableDataEntry> DataEntries = new List<MetaTableDataEntry>();


        public void AfterDataChanged()
        {
            foreach (var entry in DataEntries)
            {
                entry.Config = this;
            }
        }
#if UNITY_EDITOR

        List<MetaTableConfig> m_ConfigDep;

        [ShowInInspector]
        [ValueDropdown("OnConfigDepDropdown")]
        public List<MetaTableConfig> ConfigDep
        {
            get
            {
                if (m_ConfigDep == null)
                {
                    m_ConfigDep = new List<MetaTableConfig>();
                }
                return m_ConfigDep;
            }
            set
            {
                m_ConfigDep = value;
            }
        }

        IEnumerable OnConfigDepDropdown()
        {
            ValueDropdownList<MetaTableConfig> ret = new ValueDropdownList<MetaTableConfig>();
            var instance = MetaTableMainConfig.Instance;
            if (instance != null)
            {
                foreach (var config in instance.MetaTableConfigs)
                {
                    ret.Add(config.Name, config);

                }
            }
            return ret;
        }



        [Button("初始化目录")]
        public void InitDirs()
        {
            DirectoryUtility.ExistsOrCreate(ScriptCustomDir);
            DirectoryUtility.ExistsOrCreate(ScriptGenerateDir);

            DirectoryUtility.ExistsOrCreate(StreamResExcelDir);
            DirectoryUtility.ExistsOrCreate(StreamResScriptableObjectDir);

        }




        [Button("从Excel刷新列头")]
        public void UpdateColumnsByExcel(bool replaceId2Uuid = false)
        {
            var files = Directory.GetFiles(StreamResExcelDir, "*.xlsx");
            var pangooList = new List<string>();
            foreach (var filePath in files)
            {
                var regularFilePath = filePath.ToPath();
                var fileName = Path.GetFileNameWithoutExtension(regularFilePath);
                if (!fileName.StartsWith("~"))
                {
                    if (Entries.Find(o => o.TableName == fileName) == null)
                    {
                        var entry = new MetaTableEntry()
                        {
                            TableName = fileName,
                            Config = this,
                        };
                        entry.UpdateColumnsByExcel(replaceId2Uuid);
                        Entries.Add(entry);
                    }
                }
            }

        }





        [Button("生成代码", 30)]
        public void GenerateCode()
        {
            foreach (var entry in Entries)
            {
                entry.GeneratorCode();
            }
        }

        [Button("刷新数据通过Name", 30)]

        public void RefreshOverviewByName(bool onlyAdd = false)
        {
            foreach (var entry in Entries)
            {
                entry.RefreshOverviewByName(onlyAdd);
            }
        }

        [Button("保存配置", 30)]
        public void SaveConfig()
        {
            EditorUtility.SetDirty(this);
            AssetDatabase.SaveAssets();
            AssetDatabase.Refresh();
        }
#endif
    }
}

